package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"gitee.com/go-course/go11/skill/rpc/protobuf/blog"
	"gitee.com/go-course/go11/skill/rpc/protobuf/blog/server/auth"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	// 1. 建立网络连接
	// grpc.Dial负责和gRPC服务建立链接
	conn, err := grpc.Dial("localhost:1234",
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithPerRPCCredentials(NewConfig("admin", "123456")),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// 使用这个grpc conn 初始化一个sdk客户端
	blogClient := blog.NewBlogRpcClient(conn)

	// 发起了一次 grpc调用
	// ins, err := blogClient.CreateBlog(context.Background(), &blog.CreateBlogRequest{})
	// if err != nil {
	// 	fmt.Println(err)
	// 	os.Exit(1)
	// }

	// 这是文件上传
	// uc, err := blogClient.UploadBlog(context.Background())
	// if err != nil {
	// 	fmt.Println(err)
	// 	os.Exit(1)
	// }
	// // 获取到stream client后不断的想服务端发送数据
	// f, err := os.Open("README.md")
	// if err != nil {
	// 	fmt.Println(err)
	// 	os.Exit(1)
	// }
	// r := bufio.NewReader(f)

	// for {
	// 	line, _, err := r.ReadLine()
	// 	if err != nil {
	// 		fmt.Println(err)
	// 		os.Exit(1)
	// 	}

	// 	// 上传一行数据()
	// 	uc.Send(&blog.UploadBlogRequest{
	// 		Meta: map[string]string{"file_name": "README.md"},
	// 		Data: line,
	// 	})
	// }

	// 文件的下载
	dc, err := blogClient.DownloadBlog(
		context.Background(),
		&blog.DownloadBlogRequest{FileName: "README.md"},
	)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	for {
		resp, err := dc.Recv()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(string(resp.Data))
	}

}

// PerRPCCredentials defines the common interface for the credentials which need to
// attach security information to every RPC (e.g., oauth2).
// type PerRPCCredentials interface {
// 	// GetRequestMetadata gets the current request metadata, refreshing tokens
// 	// if required. This should be called by the transport layer on each
// 	// request, and the data should be populated in headers or other
// 	// context. If a status code is returned, it will be used as the status for
// 	// the RPC (restricted to an allowable set of codes as defined by gRFC
// 	// A54). uri is the URI of the entry point for the request.  When supported
// 	// by the underlying implementation, ctx can be used for timeout and
// 	// cancellation. Additionally, RequestInfo data will be available via ctx
// 	// to this call.  TODO(zhaoq): Define the set of the qualified keys instead
// 	// of leaving it as an arbitrary string.
// 	GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
// 	// RequireTransportSecurity indicates whether the credentials requires
// 	// transport security.
// 	RequireTransportSecurity() bool
// }

func NewConfig(cid, sk string) *Config {
	return &Config{
		ClientId:     cid,
		ClientSecret: sk,
	}
}

type Config struct {
	ClientId     string
	ClientSecret string
}

func (c *Config) GetRequestMetadata(ctx context.Context, uri ...string) (
	map[string]string, error) {
	return map[string]string{
		auth.ClientIdKey:     c.ClientId,
		auth.ClientSecretKey: c.ClientSecret,
	}, nil
}

func (c *Config) RequireTransportSecurity() bool {
	return false
}
